package top.v5it.japi.plus.common.func;

import java.util.Objects;
import java.util.function.Predicate;

/**
 * 封装基于if-else条件成功时调用模板
 *
 * @author zhanpu
 * @date 2022/5/19
 */
public abstract class FuncTemplate {

    /**
     * 按条件执行函数，条件为真执行
     *
     * @param predicate 条件
     * @param <T>       条件参数类型
     * @param <E>       可能抛出异常类型
     * @return {@link VoidFunc2}
     */
    public static <T, E extends Throwable> VoidFunc2<T, VoidFunc0<E>, E> ifVoidFunc2(Predicate<T> predicate) {
        Objects.requireNonNull(predicate);

        return (t, ifFunc) -> require(predicate.test(t), ifFunc);
    }

    /**
     * 按条件执行函数，条件为真执行
     *
     * @param testFunc 条件构造器
     * @param <E>      可能抛出异常类型
     * @return {@link VoidFunc1}
     */
    public static <E extends Throwable> VoidFunc1<VoidFunc0<E>, E> ifVoidFunc1(TestFunc<E> testFunc) {
        return ifFunc -> require(testFunc, ifFunc);
    }

    /**
     * 按条件执行函数，条件为真执行
     *
     * @param expression 条件
     * @param <E>        可能抛出异常类型
     * @return {@link VoidFunc1}
     */
    public static <E extends Throwable> VoidFunc1<VoidFunc0<E>, E> ifVoidFunc1(final boolean expression) {
        return ifFunc -> require(expression, ifFunc);
    }

    /**
     * 按条件执行函数，为真执行if函数否则执行else函数
     *
     * @param testFunc 条件构造器
     * @param <E>      可能抛出异常类型
     * @return {@link VoidFunc2}
     */
    public static <E extends Throwable> VoidFunc2<VoidFunc0<E>, VoidFunc0<E>, E> ifElseVoidFunc2(TestFunc<E> testFunc) {
        return (ifFunc, elseFunc) -> require(testFunc, ifFunc, elseFunc);
    }

    /**
     * 按条件执行函数，为真执行if函数否则执行else函数
     *
     * @param expression 条件
     * @param <E>        可能抛出异常类型
     * @return {@link VoidFunc2}
     */
    public static <E extends Throwable> VoidFunc2<VoidFunc0<E>, VoidFunc0<E>, E> ifElseVoidFunc2(final boolean expression) {
        return (ifFunc, elseFunc) -> require(expression, ifFunc, elseFunc);
    }

    /**
     * 按条件执行函数，为真执行
     *
     * @param predicate 条件
     * @param <T1>      条件参数类型
     * @param <T2>      返回值类型
     * @param <R>       返回值类型
     * @param <E>       可能抛出异常类型
     * @return {@link Func2}
     */
    public static <T1, T2 extends R, R, E extends Throwable> Func2<T1, Func0<T2, E>, R, E> ifFunc2(Predicate<T1> predicate) {
        Objects.requireNonNull(predicate);

        return (t1, ifFunc) -> requireOrNull(predicate.test(t1), ifFunc);
    }

    /**
     * 按条件执行函数，为真执行
     *
     * @param predicate 条件
     * @param <T1>      条件参数类型
     * @param <T2>      返回值类型
     * @param <R>       返回值类型
     * @param <E>       可能抛出异常类型
     * @return {@link Func3}
     */
    public static <T1, T2 extends R, R, E extends Throwable> Func3<T1, Func0<T2, E>, Func0<T2, E>, R, E> ifFunc3(Predicate<T1> predicate) {
        Objects.requireNonNull(predicate);

        return (t1, ifFunc, elseFunc) -> require(predicate.test(t1), ifFunc, elseFunc);
    }

    /**
     * 按条件执行函数，为真执行
     *
     * @param testFunc 条件构造器
     * @param <T>      返回值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return {@link Func1}
     */
    public static <T extends R, R, E extends Throwable> Func1<Func0<T, E>, R, E> ifFunc1(TestFunc<E> testFunc) {
        return ifFunc -> requireOrNull(testFunc, ifFunc);
    }

    /**
     * 按条件执行函数，为真执行
     *
     * @param expression 条件
     * @param <T>        返回值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return {@link Func1}
     */
    public static <T extends R, R, E extends Throwable> Func1<Func0<T, E>, R, E> ifFunc1(final boolean expression) {
        return ifFunc -> requireOrNull(expression, ifFunc);
    }

    /**
     * 按条件执行函数，为真执行if函数否则执行else函数
     *
     * @param testFunc 条件构造器
     * @param <T>      返回值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return {@link Func2}
     */
    public static <T extends R, R, E extends Throwable> Func2<Func0<T, E>, Func0<T, E>, R, E> ifElseFunc2(TestFunc<E> testFunc) {
        return (ifFunc, elseFunc) -> require(testFunc, ifFunc, elseFunc);
    }

    /**
     * 按条件执行函数，为真执行if函数否则执行else函数
     *
     * @param expression 条件
     * @param <T>        返回值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return {@link Func2}
     */
    public static <T extends R, R, E extends Throwable> Func2<Func0<T, E>, Func0<T, E>, R, E> ifElseFunc2(final boolean expression) {
        return (ifFunc, elseFunc) -> require(expression, ifFunc, elseFunc);
    }

    /**
     * 按条件执行函数，为真执行if函数否则执行else消费函数
     *
     * @param testFunc 条件构造器
     * @param <T>      返回值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return {@link Func2}
     */
    public static <T extends R, R, E extends Throwable> Func2<Func0<T, E>, VoidFunc0<E>, R, E> ifFuncElseVoidFunc2(TestFunc<E> testFunc) {
        return (ifFunc, elseFunc) -> requireOrNull(testFunc, ifFunc, elseFunc);
    }

    /**
     * 按条件执行函数，为真执行if函数否则执行else消费函数
     *
     * @param expression 条件
     * @param <T>        返回值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return {@link Func2}
     */
    public static <T extends R, R, E extends Throwable> Func2<Func0<T, E>, VoidFunc0<E>, R, E> ifFuncElseVoidFunc2(final boolean expression) {
        return (ifFunc, elseFunc) -> requireOrNull(expression, ifFunc, elseFunc);
    }

    /**
     * 按条件执行函数，为真执行if函数否则执行else消费函数
     *
     * @param predicate 条件
     * @param <T1>      条件参数类型
     * @param <T2>      返回值类型
     * @param <R>       返回值类型
     * @param <E>       可能抛出异常类型
     * @return {@link Func3}
     */
    public static <T1, T2 extends R, R, E extends Throwable> Func3<T1, Func0<T2, E>, VoidFunc0<E>, R, E> ifFuncElseVoidFunc3(Predicate<T1> predicate) {
        Objects.requireNonNull(predicate);

        return (t1, ifFunc, elseFunc) -> requireOrNull(predicate.test(t1), ifFunc, elseFunc);
    }

    /**
     * 按条件执行消费函数
     *
     * @param testFunc 条件构造器
     * @param <T>      消费函数输入参数类型
     * @param <E>      可能抛出异常类型
     * @return {@link VoidFunc2}
     */
    public static <T, E extends Throwable> VoidFunc2<T, VoidFunc1<T, E>, E> ifVoidFunc2(TestFunc<E> testFunc) {
        Objects.requireNonNull(testFunc);

        return ifVoidFunc2(testFunc.requireWithFuncException());
    }

    /**
     * 按条件执行消费函数
     *
     * @param expression 条件
     * @param <T>        消费函数输入参数类型
     * @param <E>        可能抛出异常类型
     * @return {@link VoidFunc2}
     */
    public static <T, E extends Throwable> VoidFunc2<T, VoidFunc1<T, E>, E> ifVoidFunc2(final boolean expression) {
        return (t, ifFunc) -> {
            if (expression) {
                ifFunc.accept(t);
            }
        };
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <E>        可能抛出异常类型
     */
    public static <E extends Throwable> void require(boolean expression, VoidFunc0<E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            if (expression) {
                ifFunc.accept();
            }
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <E>      可能抛出异常类型
     */
    public static <E extends Throwable> void require(TestFunc<E> testFunc, VoidFunc0<E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        require(testFunc.requireWithFuncException(), ifFunc);

    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <E>        可能抛出异常类型
     */
    public static <E extends Throwable> void require(boolean expression, VoidFunc0<E> ifFunc, VoidFunc0<E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            if (expression) {
                ifFunc.accept();
            } else {
                elseFunc.accept();
            }
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <E>      可能抛出异常类型
     */
    public static <E extends Throwable> void require(TestFunc<E> testFunc, VoidFunc0<E> ifFunc, VoidFunc0<E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        require(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <E>        可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc1<T, E> requireVoidFunc1(final boolean expression, VoidFunc1<T, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : t -> {
            };
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <E>      可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc1<T, E> requireVoidFunc1(TestFunc<E> testFunc, VoidFunc1<T, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireVoidFunc1(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <E>        可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc1<T, E> requireVoidFunc1(final boolean expression, VoidFunc1<T, E> ifFunc, VoidFunc1<T, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <E>      可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc1<T, E> requireVoidFunc1(TestFunc<E> testFunc, VoidFunc1<T, E> ifFunc, VoidFunc1<T, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireVoidFunc1(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <E>        可能抛出异常类型
     */
    public static <T, U, E extends Throwable> VoidFunc2<T, U, E> requireVoidFunc2(final boolean expression, VoidFunc2<T, U, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : (t, u) -> {
            };
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <E>      可能抛出异常类型
     */
    public static <T, U, E extends Throwable> VoidFunc2<T, U, E> requireVoidFunc2(TestFunc<E> testFunc, VoidFunc2<T, U, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireVoidFunc2(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <E>        可能抛出异常类型
     */
    public static <T, U, E extends Throwable> VoidFunc2<T, U, E> requireVoidFunc2(final boolean expression, VoidFunc2<T, U, E> ifFunc, VoidFunc2<T, U, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <E>      可能抛出异常类型
     */
    public static <T, U, E extends Throwable> VoidFunc2<T, U, E> requireVoidFunc2(TestFunc<E> testFunc, VoidFunc2<T, U, E> ifFunc, VoidFunc2<T, U, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireVoidFunc2(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <E>        可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc<T, E> requireVoidFunc(final boolean expression, VoidFunc<T, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : t -> {
            };
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <E>      可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc<T, E> requireVoidFunc(TestFunc<E> testFunc, VoidFunc<T, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireVoidFunc(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <E>        可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc<T, E> requireVoidFunc(final boolean expression, VoidFunc<T, E> ifFunc, VoidFunc<T, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，无返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <E>      可能抛出异常类型
     */
    public static <T, E extends Throwable> VoidFunc<T, E> requireVoidFunc(TestFunc<E> testFunc, VoidFunc<T, E> ifFunc, VoidFunc<T, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireVoidFunc(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <T>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, E extends Throwable> T requireOrNull(final boolean expression, Func0<T, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc.get() : null;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <T>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, E extends Throwable> T requireOrNull(TestFunc<E> testFunc, Func0<T, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireOrNull(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <T>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, E extends Throwable> T require(final boolean expression, Func0<T, E> ifFunc, Func0<T, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc.get() : elseFunc.get();
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <T>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, E extends Throwable> T require(TestFunc<E> testFunc, Func0<T, E> ifFunc, Func0<T, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return require(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <T>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, E extends Throwable> T requireOrNull(final boolean expression, Func0<T, E> ifFunc, VoidFunc0<E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            if (expression) {
                return ifFunc.get();
            }

            elseFunc.accept();
            return null;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <T>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, E extends Throwable> T requireOrNull(TestFunc<E> testFunc, Func0<T, E> ifFunc, VoidFunc0<E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireOrNull(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <T>        输入值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func1<T, R, E> requireFunc1(final boolean expression, Func1<T, R, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : t -> null;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <T>      输入值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func1<T, R, E> requireFunc1(TestFunc<E> testFunc, Func1<T, R, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireFunc1(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <T>        输入值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func1<T, R, E> requireFunc1(final boolean expression, Func1<T, R, E> ifFunc, Func1<T, R, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <T>      输入值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func1<T, R, E> requireFunc1(TestFunc<E> testFunc, Func1<T, R, E> ifFunc, Func1<T, R, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireFunc1(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <T>        输入1值类型
     * @param <U>        输入2值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, R, E extends Throwable> Func2<T, U, R, E> requireFunc2(final boolean expression, Func2<T, U, R, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : (t, u) -> null;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <T>      输入1值类型
     * @param <U>      输入2值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, R, E extends Throwable> Func2<T, U, R, E> requireFunc2(TestFunc<E> testFunc, Func2<T, U, R, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireFunc2(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <T>        输入1值类型
     * @param <U>        输入2值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, R, E extends Throwable> Func2<T, U, R, E> requireFunc2(final boolean expression, Func2<T, U, R, E> ifFunc, Func2<T, U, R, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <T>      输入1值类型
     * @param <U>      输入2值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, R, E extends Throwable> Func2<T, U, R, E> requireFunc2(TestFunc<E> testFunc, Func2<T, U, R, E> ifFunc, Func2<T, U, R, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireFunc2(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <T>        输入1值类型
     * @param <U>        输入2值类型
     * @param <X>        输入3值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, R, E extends Throwable> Func3<T, U, X, R, E> requireFunc3(final boolean expression, Func3<T, U, X, R, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : (t, u, x) -> null;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <T>      输入1值类型
     * @param <U>      输入2值类型
     * @param <X>      输入3值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, R, E extends Throwable> Func3<T, U, X, R, E> requireFunc3(TestFunc<E> testFunc, Func3<T, U, X, R, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireFunc3(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <T>        输入1值类型
     * @param <U>        输入2值类型
     * @param <X>        输入3值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, R, E extends Throwable> Func3<T, U, X, R, E> requireFunc3(final boolean expression, Func3<T, U, X, R, E> ifFunc, Func3<T, U, X, R, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <T>      输入1值类型
     * @param <U>      输入2值类型
     * @param <X>      输入3值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, R, E extends Throwable> Func3<T, U, X, R, E> requireFunc3(TestFunc<E> testFunc, Func3<T, U, X, R, E> ifFunc, Func3<T, U, X, R, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireFunc3(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <T>        输入1值类型
     * @param <U>        输入2值类型
     * @param <X>        输入3值类型
     * @param <Y>        输入4值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, Y, R, E extends Throwable> Func4<T, U, X, Y, R, E> requireFunc4(final boolean expression, Func4<T, U, X, Y, R, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : (t, u, x, y) -> null;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <T>      输入1值类型
     * @param <U>      输入2值类型
     * @param <X>      输入3值类型
     * @param <Y>      输入4值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, Y, R, E extends Throwable> Func4<T, U, X, Y, R, E> requireFunc4(TestFunc<E> testFunc, Func4<T, U, X, Y, R, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireFunc4(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <T>        输入1值类型
     * @param <U>        输入2值类型
     * @param <X>        输入3值类型
     * @param <Y>        输入4值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, Y, R, E extends Throwable> Func4<T, U, X, Y, R, E> requireFunc4(final boolean expression, Func4<T, U, X, Y, R, E> ifFunc, Func4<T, U, X, Y, R, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <T>      输入1值类型
     * @param <U>      输入2值类型
     * @param <X>      输入3值类型
     * @param <Y>      输入4值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, U, X, Y, R, E extends Throwable> Func4<T, U, X, Y, R, E> requireFunc4(TestFunc<E> testFunc, Func4<T, U, X, Y, R, E> ifFunc, Func4<T, U, X, Y, R, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireFunc4(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param <T>        输入1值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func<T, R, E> requireFunc(final boolean expression, Func<T, R, E> ifFunc) {
        Objects.requireNonNull(ifFunc);

        try {
            return expression ? ifFunc : t -> null;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param <T>      输入1值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func<T, R, E> requireFunc(TestFunc<E> testFunc, Func<T, R, E> ifFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);

        return requireFunc(testFunc.requireWithFuncException(), ifFunc);
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param expression 条件结果
     * @param ifFunc     if成功调用
     * @param elseFunc   else调用
     * @param <T>        输入1值类型
     * @param <R>        返回值类型
     * @param <E>        可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func<T, R, E> requireFunc(final boolean expression, Func<T, R, E> ifFunc, Func<T, R, E> elseFunc) {
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        try {
            return expression ? ifFunc : elseFunc;
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

    /**
     * 根据条件选择调用，有返回值
     *
     * @param testFunc 条件构造器
     * @param ifFunc   if成功调用
     * @param elseFunc else调用
     * @param <T>      输入1值类型
     * @param <R>      返回值类型
     * @param <E>      可能抛出异常类型
     * @return R 返回值
     */
    public static <T, R, E extends Throwable> Func<T, R, E> requireFunc(TestFunc<E> testFunc, Func<T, R, E> ifFunc, Func<T, R, E> elseFunc) {
        Objects.requireNonNull(testFunc);
        Objects.requireNonNull(ifFunc);
        Objects.requireNonNull(elseFunc);

        return requireFunc(testFunc.requireWithFuncException(), ifFunc, elseFunc);
    }

}
